package com.zmj.sy.mom.srv.aps.service;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.zmj.sy.mom.srv.aps.bean.entity.base.BaseEntity;
import com.zmj.sy.mom.srv.aps.bean.entity.base.PhaseJob;
import com.zmj.sy.mom.srv.aps.bean.entity.base.PhaseJobRef;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.Phase;
import com.zmj.sy.mom.srv.aps.bean.vo.base.*;
import com.zmj.sy.mom.srv.aps.bean.vo.phaserefactor.*;
import com.zmj.sy.mom.srv.aps.mapper.PhaseJobMapper;
import com.zmj.sy.mom.srv.aps.mapper.PhaseJobRefMapper;
import com.zmj.sy.mom.srv.aps.mapper.PhaseMapper;
import com.zmj.sy.mom.srv.aps.utils.MkBeanUtils;
import com.zmj.sy.mom.srv.aps.utils.SyExceptionUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@RequiredArgsConstructor
@Service
public class PhaseRefactorService {

    private final PhaseMapper phaseMapper;
    private final PhaseJobMapper phaseJobMapper;
    private final PhaseJobRefMapper phaseJobRefMapper;

    @Transactional(readOnly = true)
    public BaseSelectResVo jobSelect() {

        List<PhaseJob> all = phaseJobMapper.lambdaQuery().list();
        List<BaseSelectItemResVo> collect = all.stream()
                .sorted(Comparator.comparing(PhaseJob::getName))
                .map(e -> {
                    BaseSelectItemResVo item = new BaseSelectItemResVo();
                    item.setText(e.getName());
                    item.setValue(e.getId());
                    return item;
                })
                .collect(Collectors.toList());


        return BaseSelectResVo.of(collect);
    }

    @Transactional(rollbackFor = Throwable.class)
    public void jobAdd(PhaseRefactorJobAddReqVo reqVo) {
        reqVo.setName(reqVo.getName().trim());

        Integer count = phaseJobMapper.lambdaQuery().eq(PhaseJob::getName, reqVo.getName()).count();
        if (count > 0) {
            throw SyExceptionUtils.e("名称【{}】已存在", reqVo.getName().trim());
        }

        PhaseJob phaseJob = MkBeanUtils.copyProperties(reqVo, PhaseJob.class);
        phaseJobMapper.insert(phaseJob);
    }

    @Transactional(readOnly = true)
    public PhaseRefactorJobGetResVo jobGet(BaseIdReqVo reqVo) {
        PhaseJob one = phaseJobMapper.selectById(reqVo.getId());
        PhaseRefactorJobGetResVo resVo = MkBeanUtils.copyProperties(one, PhaseRefactorJobGetResVo.class);
        List<PhaseJobRef> jobRefList = phaseJobRefMapper.lambdaQuery().eq(PhaseJobRef::getPhaseJobId, reqVo.getId()).list();

        if (CollUtil.isNotEmpty(jobRefList)) {
            List<Integer> collect = jobRefList.stream().map(PhaseJobRef::getPhaseId).collect(Collectors.toList());
            List<Phase> list = phaseMapper.lambdaQuery().in(Phase::getId, collect).list();
            List<PhaseRefactorJobGetUsedResVo> collect1 = list.stream()
                    .map(e -> {
                        PhaseRefactorJobGetUsedResVo r = new PhaseRefactorJobGetUsedResVo();
                        BeanUtils.copyProperties(e, r);
                        return r;
                    })
                    .collect(Collectors.toList());
            resVo.setUsed(collect1);
        }

        return resVo;
    }

    @Transactional(rollbackFor = Throwable.class)
    public void jobEdit(PhaseRefactorJobEditReqVo reqVo) {
        reqVo.setName(reqVo.getName().trim());

        Integer count = phaseJobMapper.lambdaQuery().eq(PhaseJob::getName, reqVo.getName()).ne(PhaseJob::getId, reqVo.getId()).count();
        if (count > 0) {
            throw SyExceptionUtils.e("名称【{}】已存在", reqVo.getName().trim());
        }

        PhaseJob phaseJob = MkBeanUtils.copyProperties(reqVo, PhaseJob.class);
        phaseJobMapper.updateById(phaseJob);
    }

    @Transactional(rollbackFor = Throwable.class)
    public void jobDel(BaseIdReqVo reqVo) {
        Integer count = phaseJobRefMapper.lambdaQuery().eq(PhaseJobRef::getPhaseJobId, reqVo.getId()).count();
        if(count > 0){
            throw SyExceptionUtils.e("该任务被工序使用中，请先在工序中移除该任务");
        }

        phaseJobMapper.hardDeleteId(reqVo.getId());
    }

    @Transactional(readOnly = true)
    public BaseSelectResVo phaseSelect() {
        List<Phase> list = phaseMapper.lambdaQuery()
                .list();

        List<BaseSelectItemResVo> collect = list.stream()
                .sorted(Comparator.comparing(Phase::getMyCode))
                .map(e -> {
                    BaseSelectItemResVo item = new BaseSelectItemResVo();
                    item.setText(e.getMyCode() + "-" + e.getName());
                    item.setValue(e.getId());
                    return item;
                })
                .collect(Collectors.toList());
        return BaseSelectResVo.of(collect);
    }

    @Transactional(rollbackFor = Throwable.class)
    public void phaseAdd(PhaseRefactorPhaseAddReqVo reqVo) {

        Integer count = phaseMapper.lambdaQuery().eq(Phase::getMyCode, reqVo.getMyCode()).count();
        if (count > 0) {
            throw SyExceptionUtils.e("工序编号【{}】已存在", reqVo.getMyCode());
        }

        Phase phase = MkBeanUtils.copyProperties(reqVo, Phase.class);

        phaseMapper.insert(phase);
    }

    @Transactional(readOnly = true)
    public PhaseRefactorPhaseGetResVo phaseGet(BaseIdReqVo reqVo) {
        Phase phase = phaseMapper.selectById(reqVo.getId());
        PhaseRefactorPhaseGetResVo resVo = MkBeanUtils.copyProperties(phase, PhaseRefactorPhaseGetResVo.class);

        List<PhaseJob> allPhaseJob = phaseJobMapper.lambdaQuery().list();
        Map<Integer, PhaseJob> phaseJobIdMap = allPhaseJob.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

        List<PhaseJobRef> jobRefList = phaseJobRefMapper.lambdaQuery().eq(PhaseJobRef::getPhaseId, reqVo.getId()).list();
        Map<Integer, PhaseJobRef> phaseJobRefIdMap = jobRefList.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

        if (CollUtil.isNotEmpty(jobRefList)) {
            List<PhaseRefactorPhaseGetJobResVo> collect1 = jobRefList.stream()
                    .sorted(Comparator.comparing(PhaseJobRef::getSeq))
                    .map(e -> {
                        PhaseRefactorPhaseGetJobResVo r = new PhaseRefactorPhaseGetJobResVo();
                        BeanUtils.copyProperties(e, r);
                        PhaseJob phaseJob = phaseJobIdMap.get(e.getPhaseJobId());
                        r.setName(phaseJob.getName());
                        r.setInfo(phaseJob.getInfo());
                        return r;
                    })
                    .collect(Collectors.toList());

            resVo.setSelectJobs(collect1);
        }

        List<PhaseRefactorPhaseGetJobResVo> collect = allPhaseJob.stream()
                .filter(e -> phaseJobRefIdMap.get(e.getId()) == null)
                .sorted(Comparator.comparing(PhaseJob::getName))
                .map(e -> {
                    PhaseRefactorPhaseGetJobResVo r = new PhaseRefactorPhaseGetJobResVo();
                    BeanUtils.copyProperties(e, r);
                    r.setPhaseJobId(e.getId());
                    return r;
                })
                .collect(Collectors.toList());
        resVo.setOptionalJobs(collect);

        return resVo;
    }

    @Transactional(rollbackFor = Throwable.class)
    public void phaseEdit(PhaseRefactorPhaseEditReqVo reqVo) {
        if(reqVo.getCacheTimeUnit() == null ){
            throw SyExceptionUtils.e("工序缓存时间的单位不能为空，必须为小时、时、分、秒。");
        }
        reqVo.setName(reqVo.getName().trim());

        Integer count = phaseMapper.lambdaQuery().eq(Phase::getMyCode, reqVo.getMyCode()).ne(Phase::getId, reqVo.getId()).count();
        if (count > 0) {
            throw SyExceptionUtils.e("工序编码【{}】已存在", reqVo.getMyCode().trim());
        }
        Phase phase = MkBeanUtils.copyProperties(reqVo, Phase.class);
        phaseMapper.updateById(phase);
    }

    @Transactional(rollbackFor = Throwable.class)
    public void phaseDel(BaseIdReqVo reqVo) {
        List<PhaseJobRef> list = phaseJobRefMapper.lambdaQuery().eq(PhaseJobRef::getPhaseJobId, reqVo.getId()).list();
        if (CollUtil.isNotEmpty(list)) {
            throw SyExceptionUtils.e("该工序存在任务，请先删除选定任务。");
        }
        phaseMapper.deleteWithId(reqVo.getId());
    }

    @Transactional(rollbackFor = Throwable.class)
    public void phaseJobIn(PhaseRefactorPhaseJobInReqVo reqVo) {
        List<PhaseJobRef> list = phaseJobRefMapper.lambdaQuery()
                .eq(PhaseJobRef::getPhaseId, reqVo.getPhaseId())
                .eq(PhaseJobRef::getPhaseJobId, reqVo.getJobId())
                .list();
        if (CollUtil.isNotEmpty(list)) {
            throw SyExceptionUtils.e("该工序任务已存在。");
        }
        List<PhaseJobRef> phaseJobRefList = phaseJobRefMapper.lambdaQuery()
                .eq(PhaseJobRef::getPhaseId, reqVo.getPhaseId())
                .list();
        Integer seq = phaseJobRefList.stream()
                .max(Comparator.comparing(PhaseJobRef::getSeq))
                .orElseGet(() -> {
                    PhaseJobRef phaseJobRef = new PhaseJobRef();
                    phaseJobRef.setSeq(0);
                    return phaseJobRef;
                })
                .getSeq();
        PhaseJobRef phaseJobRef = new PhaseJobRef();
        phaseJobRef.setPhaseId(reqVo.getPhaseId());
        phaseJobRef.setPhaseJobId(reqVo.getJobId());
        phaseJobRef.setSeq(seq + 1);
        phaseJobRefMapper.insert(phaseJobRef);
    }

    @Transactional(rollbackFor = Throwable.class)
    public void phaseJobOut(BaseIdReqVo reqVo) {
        PhaseJobRef phaseJobRef = phaseJobRefMapper.selectById(reqVo.getId());
        if (ObjectUtils.isEmpty(phaseJobRef)) {
            throw SyExceptionUtils.e("未查询到选定的任务。");
        }
        phaseJobRefMapper.updateOutSeq(phaseJobRef.getSeq(), phaseJobRef.getPhaseId());
        phaseJobRefMapper.deleteOut(reqVo.getId());
    }

    @Transactional(rollbackFor = Throwable.class)
    public void phaseJobUp(BaseIdReqVo reqVo) {
        PhaseJobRef phaseJobRef = phaseJobRefMapper.selectById(reqVo.getId());
        PhaseJobRef phaseJobRefUp = phaseJobRefMapper.lambdaQuery()
                .eq(PhaseJobRef::getPhaseId, phaseJobRef.getPhaseId())
                .eq(PhaseJobRef::getSeq, phaseJobRef.getSeq() - 1)
                .one();
        if (ObjectUtils.isEmpty(phaseJobRefUp)) {
            throw SyExceptionUtils.e("该任务已是最顶端。");
        }
        Integer seq = phaseJobRef.getSeq();
        phaseJobRef.setSeq(phaseJobRefUp.getSeq());
        phaseJobRefUp.setSeq(seq);
        phaseJobRefMapper.updateById(phaseJobRef);
        phaseJobRefMapper.updateById(phaseJobRefUp);
    }

    @Transactional(rollbackFor = Throwable.class)
    public void phaseJobDown(BaseIdReqVo reqVo) {
        PhaseJobRef phaseJobRef = phaseJobRefMapper.selectById(reqVo.getId());
        PhaseJobRef phaseJobRefDown = phaseJobRefMapper.lambdaQuery()
                .eq(PhaseJobRef::getPhaseId, phaseJobRef.getPhaseId())
                .eq(PhaseJobRef::getSeq, phaseJobRef.getSeq() + 1)
                .one();
        if (ObjectUtils.isEmpty(phaseJobRefDown)) {
            throw SyExceptionUtils.e("该任务已是最底端。");
        }
        Integer seq = phaseJobRef.getSeq();
        phaseJobRef.setSeq(phaseJobRefDown.getSeq());
        phaseJobRefDown.setSeq(seq);
        phaseJobRefMapper.updateById(phaseJobRef);
        phaseJobRefMapper.updateById(phaseJobRefDown);
    }

}
